home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Visual Database / Visual dBase v5.5 / EXTERN.PAK / DBEXTERN.PRG < prev    next >
Text File  |  1995-07-18  |  14KB  |  420 lines

  1. *******************************************************************************
  2. *
  3. *  PROGRAM:      dbextern.prg
  4. *
  5. *  WRITTEN BY:   Borland Samples Group
  6. *
  7. *  DATE:         1/94
  8. *
  9. *  UPDATED:      5/94
  10. *
  11. *  REVISION:     $Revision:   2.10  $
  12. *
  13. *  VERSION:      Visual dBASE
  14. *
  15. *  DESCRIPTION:  Examples that shows how the EXTERN system can be used.
  16. *
  17. *  PARAMETERS:   Number of example to execute, 0 for all.
  18. *
  19. *  CALLS:        Windows functions and calls to dbextern.dll
  20. *
  21. *  USAGE:        DO dbextern with <example#>
  22. *                Where <example#> can be from 1 to 11, or 0 for all.
  23. *
  24. *******************************************************************************
  25.  
  26. *******************************************************************************
  27. *
  28. * Introduction:
  29. * The EXTERN system is an extension of Visual dBASE that allows
  30. * Visual dBASE programs to interface with DLL's written in Windows compatible
  31. * languages.  Exported functions from a DLL can be called from a Visual dBASE
  32. * program and those DLL functions can call back into Visual dBASE using the
  33. * mechanism of setting and executing codeblocks.
  34. * DLL functions can be called with arguments of simple type, like numeric,
  35. * float, and character, but with the inclusion of the "dbasevar.h" file
  36. * more complex Visual dBASE variables can be passed to functions in a DLL and
  37. * caught in "DBaseVar" variables.  Through these DBaseVar variables the
  38. * DLL can access and manipulate Visual dBASE variables.
  39. *
  40. * General format to declare an EXTERN function:
  41. *
  42. * EXTERN [<callconvention>] <returntype> <funcname> | <user defined funcname>
  43. *        ([parameters]) [<path>] <dllname> [FROM <expC> | <expN>]
  44. * where:
  45. * <callconvention> = CDECL or nothing for implied PASCAL.
  46. * <returntype> = One of CVOID | CSTRING | CWORD | CLONG | CLOGICAL |
  47. *                       CDOUBLE | CHANDLE | CINT | CVAR.
  48. * <funcname> = Name of the function you want to call.
  49. * <user defined funcname> = Name you give to the function. Required if
  50. *                           using the FROM option.
  51. * <parameters> = parameters of the types CSTRING | CWORD | CLONG |
  52. *                CDOUBLE | CPTR | CVAR | CHANDLE | ... | CINT | CVOID |
  53. *                CLOGICAL.
  54. * <path> = Optional path to DLL, defaults to Windows DLL search path.
  55. * <dllname> = Name of the DLL that contains the function.
  56. * FROM <expC> | <expN> = name of the function in the DLL or the ordinal #
  57. *                        of the function in the DLL if you rename the
  58. *                        function above in <user defined funcname>.
  59. *
  60. * NOTE: the CVAR and ... options apply only to DLL's that are written
  61. *       for Visual dBASE using the dbasevar.h file.
  62. *
  63. * After the EXTERN statement you can use the function just like any
  64. * other function in your Visual dBASE statements.
  65. *
  66. *
  67. * Following are examples that show different ways to use the
  68. * EXTERN system.  Most examples have a C/C++ counterpart in the
  69. * dbextern.cpp file so look there to see how things work in the DLL.
  70. *
  71. * Look in the dbasevar.h header file for more information about how
  72. * Visual dBASE variables are declared and used on the DLL side.
  73. *
  74. *******************************************************************************
  75.  
  76. parameters whichone
  77.  
  78. set talk off
  79.  
  80.  * Check parameters
  81.  
  82. tellusage = 1
  83.  
  84.  * Any parameters at all?
  85. IF pcount() > 0
  86.     * Parameter numeric?
  87.    IF type( "whichone" ) = "N"
  88.         * Parameter in range?
  89.        IF whichone <= 11 .AND. whichone >= 0
  90.            tellusage = 0
  91.        ENDIF
  92.    ENDIF
  93. ENDIF
  94.  
  95. IF tellusage = 1
  96.    ? "Usage: do dbextern with <example#>"
  97.    ? "Where <example#> can be from 1 to 11, or 0 for all."
  98.    return
  99. ENDIF
  100.  
  101. *******************************************************************************
  102. *
  103. * Example # 1.
  104. *
  105. * Some simple examples using the different types.  Also demonstrates how
  106. * to use the FROM option using the name of a PASCAL function.
  107. *
  108. *******************************************************************************
  109.  
  110. IF whichone = 1 .or. whichone = 0
  111.  
  112.    EXTERN CLOGICAL TypeTest1( CSTRING,CWORD,CDOUBLE ) dbextern.dll
  113.    EXTERN CLOGICAL T1( CSTRING,CWORD,CDOUBLE ) dbextern.dll FROM "TypeTest1"
  114.    EXTERN CDECL CDOUBLE TypeTest2( CPTR, CLONG, CVAR ) dbextern.dll
  115.  
  116.    ? "TypeTest1( should be .T. ) =", TypeTest1( "string", 123, 321.123 )
  117.    ? "T1( should be .T. ) =", T1( "string", 123, 321.123 )
  118.    d1 = 234.4
  119.    ? "TypeTest2( should be 857.50 ) =", TypeTest2( "123.1", 500, d1 )
  120.  
  121. ENDIF
  122.  
  123. *******************************************************************************
  124. *
  125. * Example # 2.
  126. *
  127. * Execute Windows API functions:
  128. *
  129. *******************************************************************************
  130.  
  131. IF whichone = 2 .or. whichone = 0
  132.  
  133.    EXTERN CWORD MessageBox( CWORD, CSTRING, CSTRING, CWORD ) user.exe
  134.    EXTERN CWORD GetFocus() user.exe
  135.  
  136.    MessageBox( GetFocus(), "Hello", "Message", 0 )
  137.  
  138. ENDIF
  139.  
  140. *******************************************************************************
  141. *
  142. * Example # 3.
  143. *
  144. * The Visual dBASE objects you send as CVAR's can be of various types.
  145. * In the DLL you can get the type of the object with Type().
  146. *
  147. *******************************************************************************
  148.  
  149. IF whichone = 3 .or. whichone = 0
  150.  
  151.    EXTERN CSTRING WhichType( CVAR ) dbextern.dll
  152.  
  153.    o = .T.
  154.    ? ".T.:", WhichType( o )
  155.    o = 123.4
  156.    ? "123.4:", WhichType( o )
  157.    o = 1234
  158.    ? "1234:", WhichType( o )
  159.    o = "hello"
  160.    ? "'hello':", WhichType( o )
  161.    o = new object()
  162.    ? "new object():", WhichType( o )
  163.    o = {|a| a=a }
  164.    ? "{|a| a=a}:", WhichType( o )
  165.  
  166. ENDIF
  167.  
  168. *******************************************************************************
  169. *
  170. * Example # 4.
  171. *
  172. * Visual dBASE variables are passed by reference and are caught on the
  173. * DLL side with a DBaseVar *.  This makes it possible to modify
  174. * Visual dBASE objects in the DLL.  This example also demonstrates how
  175. * to use the CVAR type as the return type of functions.  In the
  176. * source code of the DLL there are some hints on how to set up
  177. * the prototypes for the corresponding C/C++ functions.
  178. *
  179. *******************************************************************************
  180.  
  181. IF whichone = 4 .or. whichone = 0
  182.  
  183.        * We'll do a CDECL and a PASCAL function.
  184.    EXTERN CDECL CVAR ModifyAndAdd1( CVAR, CVAR ) dbextern.dll
  185.    EXTERN CVAR ModifyAndAdd2( CVAR, CVAR ) dbextern.dll
  186.  
  187.    d1 = 2.5
  188.    d2 = 3
  189.    result = .F.
  190.    result = ModifyAndAdd1( d1, d2 )
  191.    ? "d1 before 2.5,     after", d1
  192.    ? "d2 before 3,       after", d2
  193.    ? "result before .F., after", result
  194.  
  195.    d1 = 2.5
  196.    d2 = 3
  197.    result = .F.
  198.    result = ModifyAndAdd2( d1, d2 )
  199.    ? "d1 before 2.5,     after", d1
  200.    ? "d2 before 3,       after", d2
  201.    ? "result before .F., after", result
  202.  
  203. ENDIF
  204.  
  205. *******************************************************************************
  206. *
  207. * Example # 5.
  208. *
  209. * Members of a class object passed to a DLL are also accessible.
  210. * This leads to one way to execute Windows API functions that require
  211. * structs as parameters.  Here we call into a DLL that translates the
  212. * Visual dBASE class object into a C struct and does the actual calling. The
  213. * result of the call is piped back into a Visual dBASE object.
  214. *
  215. *******************************************************************************
  216.  
  217. IF whichone = 5 .or. whichone = 0
  218.  
  219.    EXTERN CDECL CVOID WSetRect( CVAR,CWORD,CWORD,CWORD,CWORD ) dbextern.dll
  220.    EXTERN CVOID WIntersectRect( CVAR,CVAR,CVAR ) dbextern.dll
  221.  
  222.    r1 = new Rect()
  223.    r2 = new Rect()
  224.    r3 = new Rect()
  225.    WSetRect( r1, 10,20,100,200 )
  226.    WSetRect( r2, 50,60,150,260 )
  227.    WIntersectRect( r3, r1, r2 )
  228.    ? "Rect after intersect:"
  229.    ? r3.left, r3.top, r3.right, r3.bottom
  230.  
  231. ENDIF
  232.  
  233. *******************************************************************************
  234. *
  235. * Example # 6.
  236. *
  237. * Through the use of code blocks Visual dBASE code can be executed on the fly
  238. * from inside the DLL.  This example passes 2 objects and through code
  239. * blocks the objects are compared and changed in the DLL.
  240. *
  241. *******************************************************************************
  242.  
  243. IF whichone = 6 .or. whichone = 0
  244.  
  245.    EXTERN CSTRING CheckAndChange( CVAR, CVAR ) dbextern.dll
  246.  
  247.    a = 5; b = 5
  248.    ? CheckAndChange( a, b )
  249.    ? "a and b =", a, b
  250.  
  251. ENDIF
  252.  
  253. *******************************************************************************
  254. *
  255. * Example # 7.
  256. *
  257. * Visual dBASE arrays can be accessed in the DLL.  This example computes the
  258. * average of the members of an array created on the Visual dBASE side.
  259. * The DLL function is called without any parameters.  To be able to
  260. * get at the array, the DLL function is executed through a function
  261. * pointer that is a member of the same object as the array.  Inside
  262. * the DLL you can get the "this" pointer of the object the calling
  263. * functionptr belongs to, and through that "this" pointer you can
  264. * access the array members.
  265. * Normally ofcourse you can just pass the array as a CVAR.
  266. *
  267. *******************************************************************************
  268.  
  269. IF whichone = 7 .or. whichone = 0
  270.  
  271.    EXTERN CDECL CDOUBLE ComputeAverage() dbextern.dll
  272.  
  273.    d = new array( 5 )
  274.    d.average = ComputeAverage
  275.    d[1] = 1.1
  276.    d[2] = 2.2
  277.    d[3] = 3.3
  278.    d[4] = 4.4
  279.    ? "Computed average:", d.average()
  280.  
  281. ENDIF
  282.  
  283. *******************************************************************************
  284. *
  285. * Example # 8.
  286. *
  287. * This example puts into "practice" a majority of the available
  288. * memberfunctions of the DBaseVar class.  Not much to see on this side,
  289. * but check out the corresponding function in the DLL.
  290. *
  291. *******************************************************************************
  292.  
  293. IF whichone = 8 .or. whichone = 0
  294.  
  295.    EXTERN CLONG TestABunch( CVAR ) dbextern.dll
  296.  
  297.    p = new object()
  298.    ? "TestABunch Errors:", TestABunch( p )
  299.    ? "row one of array p:", p[1,1], p[1,2], p[1,3]
  300.    ? "row two of array p:", p[2,1], p[2,2], p[2,3]
  301.  
  302. ENDIF
  303.  
  304. *******************************************************************************
  305. *
  306. * Example # 9.
  307. *
  308. * If a DLL is written in a language that can talk to DOS, you can take
  309. * advantage of that.  This example gets the complete DOS environment in
  310. * one big string.  The FROM option using ordinals is also used. Ordinal
  311. * 14 refers to GetEnvString as can be seen in the dbextern.def file.
  312. *
  313. *******************************************************************************
  314.  
  315. IF whichone = 9 .or. whichone = 0
  316.  
  317.    EXTERN CDECL CVOID GetEnvString( CVAR ) dbextern.dll
  318.    EXTERN CDECL CVOID Getit( CVAR ) dbextern.dll FROM 14
  319.  
  320.    q1 = new object()
  321.    GetEnvString( q1 )
  322.    q2 = new object()
  323.    Getit( q2 )
  324.    ? "First 40 chars of environment:"
  325.    ? substr( q1,1,20 ) + substr( q2,21,20 )
  326.  
  327. ENDIF
  328.  
  329. *******************************************************************************
  330. *
  331. * Example # 10.
  332. *
  333. * This example shows how variable number of parameters can be implemented
  334. * for CDECL functions, and how the FROM option works with CDECL functions.
  335. *
  336. *******************************************************************************
  337.  
  338. IF whichone = 10 .or. whichone = 0
  339.  
  340.    EXTERN CDECL CDOUBLE AddNumbers(...) dbextern.dll
  341.    EXTERN CDECL CDOUBLE AddThem(...) dbextern.dll FROM "_AddNumbers"
  342.  
  343.    a = 1.1
  344.    b = 2.2
  345.    c = 3.3
  346.    ? "AddNumber(...) should be 6.60:",AddNumbers( a, b, c )
  347.  
  348.    a = 2.1
  349.    b = 3.2
  350.    c = 4.3
  351.    ? "AddThem(...) should be 9.60:",AddThem( a, b, c )
  352.  
  353. ENDIF
  354.  
  355. *******************************************************************************
  356. *
  357. * Example # 11.
  358. *
  359. * This example shows how a Visual dBASE object can be combined with an "hidden"
  360. * C++ sister object.  Each Visual dBASE object has its own unique C++ object.
  361. * This allows a Visual dBASE object to "remember and store" its own details
  362. * specific to the DLL in the C++ object instead of having to save it
  363. * in the Visual dBASE object. Examples are the storing of filehandles, and
  364. * filepointers when the DLL is servicing files.
  365. * Another possibility is a form of late binding where at the time of
  366. * creation of the C++ part a choice can be made from several derived
  367. * classes based on a common parent object.
  368. *
  369. *******************************************************************************
  370.  
  371. IF whichone = 11 .or. whichone = 0
  372.  
  373.    EXTERN CWORD DLLObjectInit( CWORD ) dbextern.dll
  374.    EXTERN CSTRING Doit() dbextern.dll
  375.    EXTERN CVOID Release() dbextern.dll
  376.  
  377.     * Create 2 objects that bind with the same C++ class.
  378.    foo1 = new dBASEObject()
  379.    foo2 = new dBASEObject()
  380.    foo1.init( 1 )
  381.    foo2.init( 1 )
  382.     * One more object that binds with a different C++ class.
  383.    bar = new dBASEObject()
  384.    bar.init( 2 )
  385.  
  386.     * The first 2 object have different information stored but
  387.     * behave similarly.
  388.    ? "foo1.doit():", foo1.doit()
  389.    ? "foo2.doit():", foo2.doit()
  390.  
  391.     * The last one has different info AND behaves differently.
  392.    ? "bar.doit():", bar.doit()
  393.  
  394.    foo1.release()
  395.    foo2.release()
  396.    bar.release()
  397.  
  398. ENDIF
  399.  
  400. *******************************************************************************
  401. *
  402. * Class definitions.
  403. *
  404. *******************************************************************************
  405.  
  406. class Rect
  407.     this.left=0
  408.     this.top=0
  409.     this.right=0
  410.     this.bottom=0
  411. endclass
  412.  
  413. class dBASEObject
  414.    this.init = DLLObjectInit
  415.    this.doit = Doit
  416.    this.release = Release
  417. endclass
  418.  
  419. ********************* End of dbextern.prg ************************************
  420.